package com.hackathon2012_03_04.ryokocial;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.hackathon2012_03_04.ryokocial.ThumbnailService.Size;

/**
 * サムネイルサーブレット。
 */
public class ThumbnailServlet extends HttpServlet {
	
    /** SID */
    private static final long serialVersionUID = -2099637840301775480L;
    
    static FileItemStream imageItem=null;
    
    public static FileItemStream getImageItem() {
		return imageItem;
	}

	public static void setImageItem(FileItemStream imageItem) {
		ThumbnailServlet.imageItem = imageItem;
	}

	/**ロガー*/
    private static final Logger logger;
    static {
        logger = Logger.getLogger(
                ThumbnailServlet.class.getName());
        logger.setLevel(Level.ALL);
    }
    
    private static final ThumbnailService thumbnailService
        = new ThumbnailServiceImpl();
    
    //  画像データを受け取ってサムネイルを作成する。
    public void doPost(HttpServletRequest req, HttpServletResponse resp) 
    throws ServletException, IOException {
    	
        ServletFileUpload upload = new ServletFileUpload();
        upload.setSizeMax(950000); // アップロード可能な画像の最大サイズを800KBに制限
        
        long id=0;
        String caption=null;
    	String user=null;
    	ArrayList<String> tags=new ArrayList<String>();
    	double lat=0;
    	double lng=0;
    	FileItemIterator iterator=null;
        byte[] b=null;

        
        String latStr=null;
        String lngStr=null;
        
        try {
            iterator = upload.getItemIterator(req);
            
            while (iterator.hasNext()) {
                try {
                    FileItemStream item = iterator.next();
                    
                    // type="file"のフィールド
                    if (!item.isFormField()){	
                    	
                        processFormField(item);
                        
                        //画像アイテムを保持
                        setImageItem(item);
                        
                        b=read(item);

                    }// type="file"でないフィールドを取得
                    else{
                    	processFormField(item);
                    	
                    	String str=item.getFieldName();
                    	if(str.equals("caption")){
                    		caption=new String(read(item),"UTF-8");
                    		System.out.println(caption);
                    	}else if(str.equals("user")){
                    		user=new String(read(item),"UTF-8");
                    		System.out.println(user);
                    	}else if(str.equals("tags")){
                    		String str2=new String(read(item),"UTF-8");
                    		if(caption != null && !caption.equals("")){
                    			tags.add(caption);
                    		}
                    		String[] strings=str2.split(",");
                    		for(String s:strings){
                    			tags.add(s);
                    		}
                    		System.out.println(str2);
                    		System.out.println(tags);
                    		for(String tag:tags){
                    			System.out.println(tag);
                    		}
                    	}else if(str.equals("lat")){
                    		lat=Double.parseDouble(new String(read(item),"UTF-8"));
                    		System.out.println(""+lat);
                    	}else if(str.equals("lng")){
                    		lng=Double.parseDouble(new String(read(item),"UTF-8"));
                    		System.out.println(""+lng);
                    	}else{
                    		
                    	}
                    }
                    
                } catch ( FileUploadException e ) {
                    logger.log( Level.SEVERE, "put failed", e );
                }
            }
            
        } catch ( FileUploadException e ) {
            logger.log( Level.SEVERE, "put failed", e );
            throw new IOException(e);
        }
	    id = thumbnailService.create(
	    		b, caption, user,tags, lat, lng 
	    		);
	    
	    String url = "http://harapeco.grrr.jp/ryokocial/#detail/"+user+"/"+id+"/";
	    resp.sendRedirect(url);
    }
    
//  画像を返す。
    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
    throws ServletException, IOException {
        
        // パラメータ解決
        Long id = null;
        Size size = Size.ORIGINAL;
        try {
            id = Long.valueOf( req.getParameter( "id" ) );
        } catch ( NumberFormatException e ) {
            resp.setStatus(404);
            return;
        }
        try {
            String str = req.getParameter( "size" );
            if (str != null) size = Size.valueOf( str.toUpperCase() );
        } catch (IllegalArgumentException e) {}
        
        
        
        
        // サムネイルの取り出しと出力
        Thumbnail thumbnail = thumbnailService.getById(id);
        switch( size ) {
            case ORIGINAL: 
                write( thumbnail.getOriginal().getBytes(), resolveContentType(thumbnail.getType()), resp ); 
                break;
            case SMALL: 
                write( thumbnail.getSmall().getBytes(), "image/png", resp ); 
                break;
        }
        
    }
    
    /**
     * コンテントタイプを解決する。
     * @param type 画像種別
     * @return コンテントタイプ
     */
    String resolveContentType( String type ) {
        if ( "ICO".equals(type) ) {
            return "image/vnd.microsoft.icon";
        } else {
            return "image/" + type.toLowerCase();
        }
    }
    
    /**
     * データをレスポンスに出力する。
     * @param bytes データ
     * @param contentType コンテントタイプ
     * @param resp {@link HttpServletResponse}
     * @throws IOException 入出力例外
     */
    void write( byte[] bytes, String contentType, HttpServletResponse resp ) 
    throws IOException {
        resp.setContentType(contentType); 
        ServletOutputStream out = null;
        try {
            out = resp.getOutputStream();
            out.write(bytes, 0, bytes.length);
        } finally {
            if ( out != null ) try {
                out.close();
            } catch ( IOException e ) {
                logger.log( Level.SEVERE, "failed to close stream.", e );
            }
        }
    }

    /**
     * FileItemStreamからバイトデータを読み込む
     * @param item FileItemStream
     * @return バイトデータ
     * @throws IOException 入出力例外
     */
    byte[] read(FileItemStream item) throws IOException {
        InputStream in = null; 
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
        	try{
        		in = item.openStream();
        	}catch(Exception e){
        		e.printStackTrace();
        	}
        	try{
        		int l = 0;
        		byte[] buffer = new byte[1024];
        		while ((l = in.read(buffer, 0, buffer.length)) != -1) {
        			out.write(buffer, 0, l);
        		}
        	}catch (Exception e) {
        		
			}
            
            return out.toByteArray();
        }finally {
            if ( in != null ) try {
                in.close();
            } catch ( IOException e ) {
                logger.log( Level.SEVERE, "failed to close stream.", e );
            }
        }
    }
    
    private void processFormField(FileItemStream item)
    	throws ServletException {

    	System.out.println(item.getFieldName());
    	try {

    		System.out.println(item.getName());
    		System.out.println(item.getContentType());
    		System.out.println(item.getHeaders());
    		System.out.println(item.toString());

    	} catch (Exception e) {

    		throw new ServletException(e);
    	}
    }
}